package DAO;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import modelo.Estadio;
import modelo.Evento;
import modelo.Time;
import connection.ConnectionManager;

public class EventoDAOImp implements EventoDAO {

    /**
	 * metodos para o banco de dados
	 */
	/**
	 * metodo de inserir um evento
	 */
	private final String INSERT = "INSERT INTO Evento(id_estadio, dataEvento, id_time1, id_time2, preco_geral, preco_camarote, horas) VALUES (?,?,?,?,?,?,?)";
	/**
	 * metodo para alterar um evento
	 */
        private final String UPDATE = "UPDATE Evento SET id_estadio=?, dataEvento=?, id_time1=?, id_time2=?, preco_geral=?, preco_camarote=?, horas=? WHERE idEvento = ?";
	/**
	 * metodo para deletar um evento
	 */
        private final String DELETE = "DELETE from Evento WHERE id_evento = ?";
	/**
	 * metodo para selecionar todos os eventos
	 */
        private final String ALL = "SELECT id_evento,id_estadio, dataEvento, id_time1, id_time2, preco_geral, preco_camarote, horas  FROM Evento";
	/**
	 * metodo para mostrar o evento pelo nome inteiro ou abreviado
	 */
        private final String LIKEEstadio = "SELECT id_evento,id_estadio, dataEvento, id_time1, id_time2, preco_geral, preco_camarote, horas FROM Evento WHERE id_estadio like ?";
	/**
	 * metodo para mostrar o evento pelo identificador
	 */
        private final String ID = "SELECT id_evento,id_estadio, dataEvento, id_time1, id_time2, preco_geral, preco_camarote, horas  FROM Evento WHERE id_evento = ?";
	/**
         * metodo para mostrar todos os eventos com a data maior que a data atual
         */
        private final String DATA = "SELECT id_evento,id_estadio, dataEvento, id_time1, id_time2, preco_geral, preco_camarote, horas FROM Evento WHERE dataEvento > DATE(NOW())";
	
	/**
         * Variaveis de conex@@o 
         */
        private ConnectionManager connectionManager;
	private static Connection connection;

	EventoDAOImp() {
		this.openConnection();
	}

	public boolean isConnectionClose() {
		try {
			return connection.isClosed();
		} catch (SQLException ex) {
			return false;
		}
	}
/**
	 * Metodo para salvar um Evento
	 */
	public Evento salvar(Evento e) {
		PreparedStatement ps = null;
		try {
			/** crie uma instancia de PreparedStatement
			  * passe para ela a instrucao para realizar alteracoes em uma
			  * registro do banco
                        */
			ps = connection.prepareStatement(INSERT);

			ps.setObject(1, e.getEstadio().getIdEstadio());
			ps.setObject(2, e.getData());
			ps.setObject(3, e.getTime_1().getIdTime());
			ps.setObject(4, e.getTime_2().getIdTime());
			ps.setObject(5, e.getPreco_geral());
			ps.setObject(6, e.getPreco_camarote());
			ps.setObject(7, e.getHoras());

			ps.executeUpdate();

		} catch (SQLException ex) {
			Logger.getLogger(EventoDAOImp.class.getName()).log(Level.SEVERE,
					null, ex);
		} finally {
			this.closeConnection();
		}
		return e;

	}

	@Override
        /**
         * metodo para alterar um evento
         */
	public void alterar(Evento e) {
		PreparedStatement ps = null;
		try {
			/**
                         * crie uma instancia de PreparedStatement
			 * passe para ela a instrucao para realizar alteracoes em uma
			 * registro do banco
                        */
			ps = connection.prepareStatement(UPDATE);

			ps.setObject(1, e.getEstadio().getIdEstadio());
			ps.setObject(2, e.getData());
			ps.setObject(3, e.getTime_1().getIdTime());
			ps.setObject(4, e.getTime_2().getIdTime());
			ps.setObject(5, e.getPreco_geral());
			ps.setObject(6, e.getPreco_camarote());
			ps.setObject(7, e.getHoras());
			ps.setObject(8, e.getIdEvento());

			ps.executeUpdate();

		} catch (SQLException ex) {
			Logger.getLogger(EventoDAOImp.class.getName()).log(Level.SEVERE,
					null, ex);
		} finally {
			this.closeConnection();
		}

	}

	@Override
        /**
         * metodo para deletar um evento
         */
	public void deletar(Evento e) {
		try {
			PreparedStatement ps = null;
			ps = connection.prepareStatement(DELETE);
			/**
                         * passe para o PreparedStatement o valor do id que deve ser
			 * excluido do banco de dados
                         */
			ps.setObject(1, e.getIdEvento());

			ps.executeUpdate();

		} catch (SQLException ex) {
			Logger.getLogger(TimeDAOImp.class.getName()).log(Level.SEVERE,
					null, ex);
		} finally {
			this.closeConnection();
		}

	}

	@Override
        /**
         * metodo para listar todos os eventos
         */
	public List<Evento> findAll() {
		List<Evento> eventos = new ArrayList<Evento>();

		TimeDAO timeDAO =  DAOFactory.getTimeDAO();
		EstadioDAO estadioDAO =  DAOFactory.getEstadioDAO();

		List<Time> time_1 = new ArrayList<Time>();
		List<Time> time_2 = new ArrayList<Time>();

		List<Estadio> estadios = new ArrayList<Estadio>();

		try {
			PreparedStatement ps = null;
			ResultSet rs = null;
			ps = connection.prepareStatement(ALL);

			/**
                         * 4 Obtenha uma instancia de resultset
                         */
			rs = ps.executeQuery();
			/**
			 * estadio, dataEvento, id_time1, id_time2, preco_geral, preco_camarote, horas
			 */
			while (rs.next()) {
				Evento evento = new Evento();
				evento.setIdEvento(rs.getInt("id_evento"));
				estadios = estadioDAO
						.buscaEstadioPorId(rs.getInt("id_estadio"));
				Time time = new Time();
				time.setIdTime(rs.getInt("id_time1"));
				time_1 = timeDAO.buscaTimePorId(time);
				time.setIdTime(rs.getInt("id_time2"));
				timeDAO.openConnection();
				time_2 = timeDAO.buscaTimePorId(time);
				evento.setEstadio(estadios.get(0));
				evento.setTime_1(time_1.get(0));
				evento.setTime_2(time_2.get(0));
				evento.setData(rs.getDate("dataEvento"));
				evento.setPreco_geral(rs.getDouble("preco_geral"));
				evento.setPreco_camarote(rs.getDouble("preco_camarote"));
				evento.setHoras(rs.getTime("horas"));
				eventos.add(evento);
				/**
                                 * 5 crie uma instancia de cidade com os dados
				 * obtidos do banco e adicione a lista de cidadesf
                                 */

			}

		} catch (SQLException ex) {
			Logger.getLogger(EventoDAOImp.class.getName()).log(Level.SEVERE,
					null, ex);
		} finally {
			this.closeConnection();
		}
		return eventos;
	}

	@Override
        /**
	 * testando se a conexao com o banco esta fechada
	 */
	public void openConnection() {
		if (connectionManager == null) {
			connectionManager = ConnectionManager.getInstance();
		}

		if (connection == null) {
			connection = connectionManager.getConnection();
		}

		if (isConnectionClose()) {
			connection = connectionManager.getConnection();
		}

	}

	@Override
        /**
	 * abrindo conexao com banco de dados
	 */
	public void closeConnection() {
		if (connection != null && connectionManager != null) {
			if (!this.isConnectionClose()) {
				connectionManager.closeConnection(connection);
			}
		}

	}

	@Override
        /**
         * metodo para buscar evento por estadio
         */
	public List<Evento> buscaEventoPorEstadio(Evento evento) {
		List<Evento> eventos = new ArrayList<Evento>();

		TimeDAO timeDAO =  DAOFactory.getTimeDAO();
		EstadioDAO estadioDAO =  DAOFactory.getEstadioDAO();

		Time time_1 = new Time();
		Time time_2 = new Time();

		List<Estadio> estadios = new ArrayList<Estadio>();

		PreparedStatement ps = null;
		ResultSet rs = null;

		try {
			ps = connection.prepareStatement(LIKEEstadio);
			/**
                         * 6 informe o parmetro para instrucao like
                         */
			ps.setObject(1, evento.getEstadio());

			rs = ps.executeQuery();
			/**
			 * estadio, dataEvento, time_1, time_2, preco_geral, preco_camarote, horas
			 */
			while (rs.next()) {

				estadios = estadioDAO
						.buscaEstadioPorId(rs.getInt("id_estadio"));
				Time time = new Time();
				time.setIdTime(rs.getInt("id_time1"));
				time_1 = timeDAO.buscaTimePorId(time).get(0);
				time.setIdTime(rs.getInt("id_time2"));
				time_2 = timeDAO.buscaTimePorId(time).get(0);

				eventos.add(new Evento(rs.getInt("id_evento"), estadios.get(0),
						rs.getDate("dataEvento"), time_1, time_2, rs
								.getDouble("preco_geral"), rs
								.getDouble("preco_camarote"), rs
								.getTime("horas")));

			}
		} catch (SQLException ex) {
			Logger.getLogger(TimeDAOImp.class.getName()).log(Level.SEVERE,
					null, ex);
		} finally {
			this.closeConnection();
		}
		return eventos;
	}

	@Override
        /**
         * metodo para buscar evento por identificador
         */
	public List<Evento> buscaEventoPorId(int idEvento) {
		List<Evento> eventos = new ArrayList<Evento>();

		TimeDAO timeDAO =  DAOFactory.getTimeDAO();
		EstadioDAO estadioDAO =  DAOFactory.getEstadioDAO();
		Time time_1 = new Time();
		Time time_2 = new Time();

		List<Estadio> estadios = new ArrayList<Estadio>();

		PreparedStatement ps = null;
		ResultSet rs = null;

		try {
			ps = connection.prepareStatement(ID);
			/**
                         *  informe o parmetro para instrucao ID
                         */
			ps.setObject(1, idEvento);

			rs = ps.executeQuery();
			/**
			 * estadio, dataEvento, time_1, time_2, preco_geral, preco_camarote, horas
			 */
			while (rs.next()) {

				estadios = estadioDAO.buscaEstadioPorId(rs.getInt("id_estadio"));
				Time time = new Time();
				time.setIdTime(rs.getInt("id_time1"));
				time_1 = timeDAO.buscaTimePorId(time).get(0);
				time.setIdTime(rs.getInt("id_time2"));
				timeDAO.openConnection();
				time_2 = timeDAO.buscaTimePorId(time).get(0);

				eventos.add(new Evento(rs.getInt("id_evento"),
						estadios.get(0),
						rs.getDate("dataEvento"), 
						time_1,
						time_2,
						rs.getDouble("preco_geral"),
						rs.getDouble("preco_camarote"),
						rs.getTime("horas")));

			}
		} catch (SQLException ex) {
			Logger.getLogger(TimeDAOImp.class.getName()).log(Level.SEVERE,
					null, ex);
		} finally {
			this.closeConnection();
		}
		return eventos;
	}

	@Override
        /**
         * metodo para buscar evento por data
         */
	public List<Evento> buscaEventoPorData() {
		List<Evento> eventos = new ArrayList<Evento>();

		TimeDAO timeDAO =  DAOFactory.getTimeDAO();
		EstadioDAO estadioDAO =  DAOFactory.getEstadioDAO();

		Time time_1 = new Time();
		Time time_2 = new Time();

		List<Estadio> estadios = new ArrayList<Estadio>();

		PreparedStatement ps = null;
		ResultSet rs = null;

		try {
			ps = connection.prepareStatement(DATA);
			/**
                         * informe o parmetro para instrucao like
                         */ 

			rs = ps.executeQuery();
			/**
			 * estadio, dataEvento, time_1, time_2, preco_geral, preco_camarote, horas
			 */
			while (rs.next()) {

				estadios = estadioDAO.buscaEstadioPorId(rs.getInt("id_estadio"));
				Time time = new Time();
				time.setIdTime(rs.getInt("id_time1"));
				time_1 = timeDAO.buscaTimePorId(time).get(0);
				time.setIdTime(rs.getInt("id_time2"));
				timeDAO.openConnection();
				time_2 = timeDAO.buscaTimePorId(time).get(0);

				eventos.add(new Evento(rs.getInt("id_evento"),
						estadios.get(0),
						rs.getDate("dataEvento"), 
						time_1,
						time_2,
						rs.getDouble("preco_geral"),
						rs.getDouble("preco_camarote"),
						rs.getTime("horas")));

			}
		} catch (SQLException ex) {
			Logger.getLogger(TimeDAOImp.class.getName()).log(Level.SEVERE,
					null, ex);
		} finally {
			this.closeConnection();
		}
		return eventos;
	}

}
